import React from 'react';
import PropTypes from 'prop-types';
import {
  Row,
  Col,
  Menu,
  Table,
  message,
  Popover,
  Tooltip,
  Checkbox,
  Dropdown,
  Popconfirm,
} from 'antd';
// import { connect } from 'umi';
import {
  ColumnHeightOutlined,
  FullscreenOutlined,
  FullscreenExitOutlined,
  ReloadOutlined,
  SettingOutlined,
  // PushpinOutlined,
  // VerticalAlignMiddleOutlined,
  // PushpinOutlined,
  // FilterOutlined,
} from '@ant-design/icons';
import { Resizable } from 'react-resizable';
import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd';
import localStorage from '../utils/localStorage';
import EventsBus from '../utils/events';
import connect from '../context/connect';

const save = (nextColumns) => {
  const path = window.location.pathname;
  const saveId = `set1${localStorage.getItem('userId')}${path.replace(
    /\//g,
    '-',
  )}`;
  let preList = JSON.parse(localStorage.getItem(saveId)) || [];
  const nextMap = {};
  nextColumns.forEach((i) => {
    nextMap[i.dataIndex] = i.width;
  });
  preList = preList.map((i) => ({ ...i, width: nextMap[i.dataIndex] }));
  localStorage.setItem(saveId, JSON.stringify(preList));
};

const ResizeableTitle = (props) => {
  const { onResize, ...restProps } = props;
  const { width } = props;
  if (!width) {
    return <th {...restProps} />;
  }
  if (
    props.children &&
    props.children.length > 0 &&
    props.children.indexOf('操作') > -1
  ) {
    return <th {...restProps} />;
  }

  return (
    <Resizable
      width={width}
      height={0}
      onResize={onResize}
      handle={
        <span
          className="react-resizable-handle"
          onClick={(e) => {
            e.stopPropagation();
          }}
        />
      }
      draggableOpts={{
        enableUserSelectHack: false,
      }}
    >
      <th {...restProps} />
    </Resizable>
  );
};

class FlexibleTable extends React.PureComponent {
  components = {
    header: {
      cell: ResizeableTitle,
    },
  };

  constructor(props) {
    super(props);
    this.state = {
      columns: [],
      columnsLocal: [],
      filterLocal: [],
      tableId: null,
      filterId: null,
      columnsId: null,
      tableCheckedAll: true,
      filterCheckedAll: true,
      pageSizeId: null,
      checkout: 'table',
      columnHeight: 'middle',
      fixed: false,
      sorter: {}, // 保存一份排序数据

      fixedTop: 48,
    };

    // this.i = 0;
  }

  componentDidMount() {
    const props = this.props;
    const path = window.location.pathname;
    const tableId = `table${localStorage.getItem('userId')}${path.replace(
      /\//g,
      '-',
    )}`;
    const columnsId = `set1${localStorage.getItem('userId')}${path.replace(
      /\//g,
      '-',
    )}`;
    const filterId = `setFilter${localStorage.getItem('userId')}${path.replace(
      /\//g,
      '-',
    )}`;

    const columnHeight = props.size;
    this.setState({ tableId, filterId, columnsId, columnHeight });

    this.defaultPageSize();
    this.defaultLocalColumns();
    this.defaultLocalFilter();
    // 监听事件
    // window.addEventListenter 监听resize会导致多页面监听事件-事件重复触发
    // 监听是否全屏事件
    // todo dom0级事件会覆盖，不知道吗？
    window.onresize = this.scrollOnTableResize;
    document.addEventListener('scroll', this.scrollOnTableFixed);
  }

  componentWillReceiveProps(nextProps) {
    const props = this.props;
    const state = this.state;
    try {
      const preGlobal = props.settings;
      const nextGlobal = nextProps.settings;
      const style = state.fixedStyle;
      // 多工作台，对固定表头的影响
      if (nextProps.settings.mutilModel && state.fixedTop !== 88) {
        this.setState({
          fixedTop: 88,
          fixedStyle: {
            ...style,
            top: 88,
          },
        });
      }
      if (!nextProps.settings.mutilModel && state.fixedTop !== 48) {
        this.setState({
          fixedTop: 48,
          fixedStyle: {
            ...style,
            top: 48,
          },
        });
      }

      // 判断左侧菜单缩进（左侧菜单对，固定表头的影响）
      if (preGlobal.collapsed !== nextGlobal.collapsed) {
        if (state.fixed) {
          // 判断table 列表fixed
          // const width = nextGlobal.collapsed ? -128 : 128;
          const style = state.fixedStyle;
          const fixedStyle = {
            ...style,
            width: 'auto',
          };
          if (nextGlobal.collapsed) {
            fixedStyle.left = 80 + 24 + 24 + 'px';
            fixedStyle.right = 24 + 24 + 'px';
          } else {
            fixedStyle.left = 208 + 24 + 24 + 'px';
            fixedStyle.right = 24 + 24 + 'px';
          }
          this.setState({ fixedStyle });
        }
      }
      // 判断 菜单模式改变
      // todo 无效代码

      // 浅比较
      const preArr = state.columns;
      const currArr = nextProps.columns;
      if (!preArr || !currArr) {
        return;
      }
      const preShowArray = preArr.filter((item) => item.show);
      const currShowArray = currArr.filter((item) => item.show);

      if (preShowArray.length !== currShowArray.length) {
        // 个数更新
        this.defaultLocalColumns();
        return;
      }
      // todo 冗余代码 后面应该统一（需要简化逻辑，为只要有一个变化，那么就重置）
      for (let i = 0; i < currArr.length; i += 1) {
        // 字段更新
        const curr = currArr[i] || {};
        const pre = preArr[i] || {};
        if (curr.dataIndex !== pre.dataIndex) {
          // 字段名称变换
          this.defaultLocalColumns();
          return;
        }
      }
    } catch (e) {
      // eslint-disable-next-line
      console.log(e);
    }
  }

  componentWillUnmount() {
    const state = this.state;
    window.onresize = null;
    document.removeEventListener('scroll', this.scrollOnTableFixed);
    // todo  重复代码 .tableNormal${state.tableId} .ant-table-content
    const tableScroll = document.querySelector(
      `.tableNormal${state.tableId} .ant-table-content`,
    );
    const tableFixed = document.querySelector(
      `.tableFixed${state.tableId} .ant-table-content`,
    );
    if (tableScroll) {
      tableScroll.removeEventListener('scroll', this.scrollOnTableFixed);
    }
    if (tableFixed) {
      tableFixed.addEventListener('scroll', this.tableFixedScrollOnChange);
    }
  }

  // 默认设置表格pageSize
  defaultPageSize = () => {
    const state = this.state;
    const props = this.props;
    const page = props.page || props.type;
    // const paginationStr = props.refreshPagination || 'pagination';
    const path = window.location.pathname;
    if (page) {
      // todo 需要规范储存名称 `table${localStorage.getItem('userId')}${path.replace(/\//g, '-')}`;
      const sizeId =
        state.tableId ||
        `table${localStorage.getItem('userId')}${path.replace(/\//g, '-')}`;
      // const pagination = props.modelState[page][paginationStr];
      try {
        const tableStr = localStorage.getItem(sizeId);
        const tableCon = JSON.parse(tableStr) || [];
        const pageSize = tableCon[0] || 20;
        const columnHeight = tableCon[1] || props.size || 'middle';

        if (props.setPagination) {
          if (props.setPagination.current) {
            props.setPagination.current.pageSize = Number(pageSize);
          }
        }

        if (columnHeight !== props.size) {
          this.setState({ columnHeight });
        }
      } catch (e) {
        message.error(`数据出错了,{${e}}刷新试试`);
        // eslint-disable-next-line
        console.log(e);
      }
    }
  };

  // 更新保存本地cloumns数据
  defaultLocalColumns = () => {
    // 进入页面初始化 进行默认更新保存
    const state = this.state;
    const props = this.props;
    const columns = props.columns || [];
    const path = window.location.pathname;
    // todo 命名不规范 不统一 重复代码
    const pathId =
      state.columnsId ||
      `set1${localStorage.getItem('userId')}${path.replace(/\//g, '-')}`;
    const localColumnsStr = localStorage.getItem(pathId);
    // 获取各数组
    const columnsTitleArray = columns.map((item) => item.title);
    const localColumnsArray =
      (localColumnsStr && JSON.parse(localColumnsStr)) || [];
    const localTitleArray = localColumnsArray.map((item) => item.title);

    const columnsList = [];
    // todo 这段比较逻辑为 待优化代码
    // 第一次循环，取保存数据，判断删除数据
    localColumnsArray.forEach((item) => {
      const index = columnsTitleArray.indexOf(item.title);
      const columnsItem = columns[index];
      const show = [false, true, undefined].indexOf(item.show);
      if (index !== -1) {
        columnsList.push({
          ...columnsItem,
          show: !!show,
          width: Number(String(item.width).replace('px', '')) || 0,
          fixed: item.fixed,
        });
      }
    });
    // 第二次循环，判断新增数据
    columns.forEach((item, i) => {
      const index = localTitleArray.indexOf(item.title);
      if (index === -1) {
        const itemQuery = {
          show: true,
          width: Number(String(item.width).replace('px', '')) || 0,
          title: item.title,
          fixed: item.fixed,
          disabled: item.disabled,
        };
        if (!item.width) {
          itemQuery.width = 0;
        } else if (!isFinite(item.width)) {
          itemQuery.width = Number(String(item.width).replace('px', '')) || 0;
        }

        if (['操作'].includes(item.title) || !item.dataIndex) {
          itemQuery.width = Number(String(item.width).replace('px', '')) || 0;
          itemQuery.show = true;
          itemQuery.disabled = true;
        }
        // 插入
        if (i > columnsList.length) {
          columnsList.push({ ...item, ...itemQuery });
        } else {
          columnsList.splice(i, 0, { ...item, ...itemQuery });
        }
      }
    });
    const column = columnsList
      .map((i) => {
        const item = i;
        if (!item.width) {
          item.width = 150;
        }
        return item;
      })
      .filter((item) => item.show);

    // 判断if需要浮动(显示6 个以下)
    if (column.length <= 6) {
      for (let i = 0; i < column.length; i += 1) {
        column[i].fixed = null;
      }
    } else {
      // const columnRight = column.filter(item => item.fixed === 'right');
      // for (let i = 0; i < column.length; i += 1) {
      //   if (column[i].title === '操作' && !column[i].fixed) {
      //     column[i].fixed = 'right';
      //   }
      //   if (i > column.length - columnRight.length) {
      //     if (!column[i].fixed) {
      //       // 去掉几个宽度以自适应
      //       column[i].width = null;
      //     }
      //   }
      // }
    }

    // 是否为全选
    let checkedAll = true;
    if (column.length !== columnsList.length) {
      checkedAll = false;
    }

    this.setState(
      {
        checkedAll,
        columns: [...column],
        columnsLocal: [...columnsList],
      },
      () => {
        const columnStr = JSON.stringify(columnsList);
        localStorage.setItem(pathId, columnStr);
      },
    );
  };

  defaultLocalFilter = () => {
    const state = this.state;
    const path = window.location.pathname;
    const filterId =
      state.filterId ||
      `setFilter${localStorage.getItem('userId')}${path.replace(/\//g, '-')}`;
    const filterLocalStr = localStorage.getItem(filterId);
    const filterLocalArr = (filterLocalStr && JSON.parse(filterLocalStr)) || [];
    this.setState({
      filterLocal: [...filterLocalArr],
    });
  };

  tableFixedScrollOnChange = () => {
    const { tableId } = this.state;
    const classArr = {
      ts: `.tableNormal${tableId} .ant-table-content`, // table滚动条(当前)
      fs: `.tableFixed${tableId} .ant-table-content`, // 头部滚动条（当前）
    };
    const tableScroll = document.querySelector(classArr.ts);
    const tableFixedScroll = document.querySelector(classArr.fs);
    tableScroll.scrollTo(tableFixedScroll.scrollLeft, 0);
  };

  // 滚动表头浮动
  scrollOnTableFixed = () => {
    const state = this.state;
    const props = this.props;
    const settings = props.settings;
    const classArr = {
      w: '.ant-spin-nested-loading',
      c: '.table-container-fixed', // 整个table组件包裹层
      t: '.tableNormal .ant-table-content', // table滚动条
      f: '.tableFixed .ant-table-content', // 头部滚动条
      ts: `.tableNormal${state.tableId} .ant-table-content`, // table滚动条(当前)
      fs: `.tableFixed${state.tableId} .ant-table-content`, // 头部滚动条（当前）
    };

    const top = state.fixedTop || 48;
    const domC = document.querySelector(classArr.c);
    const tableNormal = document.querySelector(classArr.t);
    const tableScroll = document.querySelector(classArr.ts);

    // 表格头部浮起来
    if (
      domC &&
      tableScroll.getBoundingClientRect().top <= top &&
      !state.fixed
    ) {
      const fixedStyle = {
        position: 'fixed',
        zIndex: 11,
        background: '#f0f2f5',
        width: domC.clientWidth,
        transition: 'all 0.2s ease-in',
        top: settings.hiddenHeader ? top : top,
      };
      // fixed 判断是否 固定header
      this.setState({ fixed: true, fixedStyle }, () => {
        try {
          const tableFixed = document.querySelector(classArr.fs);
          domC.scrollTo(0, 1);
          if (tableFixed) {
            tableFixed.scrollTo(tableNormal.scrollLeft, 10);
          }
          // 双向监听
          if (tableScroll) {
            tableScroll.addEventListener('scroll', this.scrollOnTableFixed);
          }
          // 双向监听
          if (tableFixed) {
            tableFixed.addEventListener(
              'scroll',
              this.tableFixedScrollOnChange,
            );
          }
        } catch (e) {
          console.log(e);
        }
      });
    }

    // 表格头部浮下去
    if (state.fixed) {
      try {
        const tableFixedScroll = document.querySelector(classArr.fs);
        if (tableScroll && tableFixedScroll) {
          tableFixedScroll.scrollTo(tableScroll.scrollLeft, 0);
        }
        if (domC && tableScroll.getBoundingClientRect().top >= top) {
          this.setState({ fixed: false });
        }
      } catch (e) {
        // eslint-disable-next-line
        console.log(e);
      }
    }
  };

  // 全屏，改变窗口大小等
  scrollOnTableResize = () => {
    const state = this.state;
    const props = this.props;
    if (state.fixed) {
      // 表头状态
      const style = state.fixedStyle;
      const domW = document.querySelector('.table-container-fixed');
      const fixedStyle = {
        // 更新表头长度
        ...style,
        width: domW.clientWidth,
      };
      this.setState({ fixedStyle });
    }

    const global = props.settings;
    // chrome 浏览器
    // const isBoolen0 = [false,true,null,undefined].indexOf(document.webkitIsFullScreen)
    // 判断全屏
    const isHeight = Math.abs(
      document.documentElement.clientHeight - window.screen.height,
    );
    const isFull0 =
      document.fullscreenElement ||
      document.isFullScreen ||
      document.webkitIsFullScreen;
    const isFull1 =
      document.documentElement.clientHeight >= window.screen.height;
    const isFull2 = !(state.isFull && Math.abs(isHeight - state.isFull) > 120);

    if ((isFull0 || isFull1) && isFull2) {
      this.setState({ isFull: isHeight, isFullScreen: true });
      // if (global.sider && global.sider.includes('top')) {
      //   // deHeader.style.top = 0
      //   props.dispatch({
      //     type: 'global/updateState',
      //     payload: {
      //       preCollapsed: global.collapsed,
      //       collapsed: false,
      //     },
      //   });
      // } else {
      //   // deHeader.style.top = '-45px'
      //   props.dispatch({
      //     type: 'global/updateState',
      //     payload: {
      //       preCollapsed: global.collapsed,
      //       collapsed: true,
      //     },
      //   });
      // }
    } else if (global.hiddenHeader) {
      this.setState({ isFullScreen: false });
      // deHeader.style.top = 0
      this.setState({ isFullScreen: false });
      // props.dispatch({
      //   type: 'global/updateState',
      //   payload: {
      //     collapsed: global.preCollapsed,
      //   },
      // });
    } else if (state.isFullScreen) {
      this.setState({ isFullScreen: false });
    }
  };

  // 更新 localColumns
  updateLocalColumns = () => {
    const state = this.state;
    const path = window.location.pathname;
    const columnsLocal = [];
    if (Array.isArray(state.columnsLocal)) {
      state.columnsLocal.forEach((item) => {
        const show = [false, true, undefined].indexOf(item.show);
        const itemQ = { ...item };
        itemQ.width = Number(String(item.width).replace('px', '')) || 0;
        itemQ.show = !!show;
        columnsLocal.push(itemQ);
      });
    }
    const columns = columnsLocal.filter((item) => item.show);
    if (columns.length <= 6) {
      for (let i = 0; i < columns.length; i += 1) {
        columns[i].fixed = null;
      }
    }

    this.setState({ columns }, () => {
      const columnsId =
        state.columnsId ||
        `set1${localStorage.getItem('userId')}${path.replace(/\//g, '-')}`;
      const columnsLocalStr = JSON.stringify(columnsLocal);
      localStorage.setItem(columnsId, columnsLocalStr);
    });
  };

  updateLocalFilter = () => {
    const state = this.state;
    const path = window.location.pathname;
    const filterLocal = state.filterLocal;
    try {
      const filterId =
        state.filterId ||
        `setFilter${localStorage.getItem('userId')}${path.replace(/\//g, '-')}`;
      const filterLocalStr = JSON.stringify(filterLocal);
      localStorage.setItem(filterId, filterLocalStr);
      EventsBus.emit(`${path}=refresh`, filterLocal);
      this.defaultLocalFilter();
    } catch (e) {
      console.log(e);
    }
  };

  // 保存当前列宽
  handleResize = (index) => (e, { size }) => {
    this.setState(({ columns, columnsLocal }) => {
      const nextColumns = [...columns];
      const nextLocal = [...columnsLocal];
      nextColumns[index] = {
        ...nextColumns[index],
        width: size.width,
      };
      nextLocal.forEach((item, i) => {
        const itemTitle = item.title === nextColumns[index].title;
        const dataIndex = item.dataIndex === nextColumns[index].dataIndex;

        if (dataIndex || itemTitle) {
          nextLocal[i] = {
            ...columnsLocal[i],
            width: size.width,
          };
        }
      });
      save(nextColumns);
      return { columns: nextColumns, columnsLocal: nextLocal };
    });
  };

  // 用于固定表格头
  // todo 待定
  onPageChangeHeader = (page, filters, sort) => {
    const { pagination } = this.props;
    const state = this.state;
    const sorter = sort || state.sorter;
    this.onPageChange(pagination, filters, sorter);
    this.setState({
      sorter,
    });
  };

  // 保存当前页码
  onPageChange = (page, filters, sort) => {
    const state = this.state;
    const sorter = sort || state.sorter;
    // 保存一份排序数据，防止 onPageChange在独立调用的时候，没有sorter数据
    this.setState({
      sorter,
    });
    const { onChange } = this.props;
    const path = window.location.pathname;
    const pageSizeId =
      state.pageSizeId ||
      `table${localStorage.getItem('userId')}${path.replace(/\//g, '-')}`;
    if (onChange && page) {
      const tableCon = [page.pageSize, state.columnHeight];
      const tableStr = JSON.stringify(tableCon);
      localStorage.setItem(pageSizeId, tableStr);
      onChange(page, filters, sorter);
    } else if (onChange && !page) {
      // 没有分页的情况
      onChange({}, filters, sorter);
    }
  };

  // 切换列表类型
  columnHeightChange = (target) => {
    const props = this.props;
    const callback = () => this.onPageChange(props.pagination);
    this.setState({ columnHeight: target.key }, callback);
  };

  // 全屏操作
  // todo 太复杂了，需要简化
  tableFullScreen = () => {
    // const state = this.state
    const de = document.documentElement;
    const fullScreen =
      document.isFullScreen ||
      document.mozIsFullScreen ||
      document.webkitIsFullScreen;
    if (!de) {
      return;
    }
    if (!fullScreen) {
      if (de.requestFullscreen) {
        de.requestFullscreen();
      } else if (de.mozRequestFullScreen) {
        de.mozRequestFullScreen();
      } else if (de.webkitRequestFullScreen) {
        de.webkitRequestFullScreen();
      }
    }

    if (fullScreen) {
      if (document.exitFullscreen) {
        if (
          document.isFullScreen ||
          document.mozIsFullScreen ||
          document.webkitIsFullScreen
        ) {
          document.exitFullscreen();
        } else {
          // F11 全屏API  HTML5 无法调用
          message.error('请按键盘 F11 退出全屏');
        }
      } else if (document.mozCancelFullScreen) {
        document.mozCancelFullScreen();
      } else if (document.webkitCancelFullScreen) {
        document.webkitCancelFullScreen();
      }
    }
  };

  // 固钉
  tableFixedChange = (event, i) => {
    const state = this.state;
    const props = this.props;
    const columnsLocal = [...state.columnsLocal];
    const leftFixed = columnsLocal.filter((item) => item.fixed === 'left');
    const rightFixed = columnsLocal.filter((item) => item.fixed === 'right');

    if (props.disabled) {
      message.error('该表格不允许浮动固定');
      return;
    }
    // 判断最多固定 6 个
    if (!event.fixed && leftFixed.length + rightFixed.length >= 6 && i) {
      message.error('超过固定最大值');
      return;
    }
    if (!i && event.title === '操作') {
      message.error('操作按钮不能取消');
      return;
    }
    if (i && event.disabled) {
      message.error('该钮不允许操作');
      return;
    }
    state.columnsLocal.forEach((item, j) => {
      // dataIndex 或者 title 判断元素
      if (item.dataIndex === event.dataIndex || item.title === event.title) {
        if (i === -1) {
          // 左固定
          const [columnsItem] = columnsLocal.splice(j, 1);
          columnsItem.fixed = 'left';
          columnsLocal.splice(leftFixed.length, 0, columnsItem);
        }
        if (i === 0) {
          // 取消
          const [columnsItem] = columnsLocal.splice(j, 1);
          if (item.fixed === 'left') {
            columnsItem.fixed = null;
            columnsLocal.splice(leftFixed.length - 1, 0, columnsItem);
          }
          if (item.fixed === 'right') {
            columnsItem.fixed = null;
            columnsLocal.splice(
              columnsLocal.length - rightFixed.length + 1,
              0,
              columnsItem,
            );
          }
        }
        if (i === 1) {
          // 右固定
          const [columnsItem] = columnsLocal.splice(j, 1);
          columnsItem.fixed = 'right';
          columnsLocal.splice(
            columnsLocal.length - rightFixed.length,
            0,
            columnsItem,
          );
        }
      }
    });

    this.setState({ columnsLocal }, this.updateLocalColumns);
  };

  // 刷新页面
  pageReLoad = () => {
    const { pagination } = this.props;
    this.onPageChange(pagination);
  };

  // 拖拽结束
  onTableDragEnd = (result) => {
    const state = this.state;
    const props = this.props;
    if (props.disabled) {
      message.error('该表格不允许拖拽排序');
      return;
    }
    if (!result.destination) {
      return;
    }
    const columnsLocal = this.reorder(
      state.columnsLocal,
      result.source.index,
      result.destination.index,
    );
    const columns = columnsLocal.filter((item) => item.show);
    this.setState(
      {
        columnsLocal,
        columns: [...columns],
      },
      this.updateLocalColumns,
    );
  };

  // 拖拽左侧结束
  onTableDragLeftEnd = (result) => {
    const state = this.state;
    const props = this.props;
    if (props.disabled) {
      message.error('该表格不允许拖拽排序');
      return;
    }
    if (!result.destination) {
      return;
    }
    const columnsLocal = state.columnsLocal;
    const columnsLeft = state.columnsLocal.filter(
      (item) => item.fixed === 'left',
    );
    const columnsLocalLeft = this.reorderLeft(
      columnsLeft,
      result.source.index,
      result.destination.index,
    );
    columnsLocal.splice(0, columnsLeft.length, ...columnsLocalLeft);
    const columns = columnsLocal.filter((item) => item.show);
    this.setState(
      {
        columnsLocal,
        columns: [...columns],
      },
      this.updateLocalColumns,
    );
  };

  // 拖拽右侧结束
  onTableDragRightEnd = (result) => {
    const state = this.state;
    const props = this.props;
    if (props.disabled) {
      message.error('该表格不允许拖拽排序');
      return;
    }
    if (!result.destination) {
      return;
    }
    const columnsLocal = state.columnsLocal;
    const columnsRight = state.columnsLocal.filter(
      (item) => item.fixed === 'right',
    );
    const columnsLocalRight = this.reorderLeft(
      columnsRight,
      result.source.index,
      result.destination.index,
    );

    columnsLocal.splice(
      columnsLocal.length - columnsRight.length,
      columnsRight.length,
      ...columnsLocalRight,
    );
    const columns = columnsLocal.filter((item) => item.show);
    this.setState(
      {
        columnsLocal,
        columns: [...columns],
      },
      this.updateLocalColumns,
    );
  };

  // 拖拽结束
  onFilterDragEnd = (result) => {
    const state = this.state;
    if (!result.destination) {
      return;
    }
    const filterLocal = this.reorder(
      state.filterLocal,
      result.source.index,
      result.destination.index,
    );

    this.setState({ filterLocal: [...filterLocal] }, this.updateLocalFilter);
  };

  // 封装转换位置
  // todo 就是数组位置交换，待优化
  reorder = (list, startIndex, endIndex) => {
    const result = Array.from(list);
    const left = result.filter((item) => item.fixed === 'left');
    const startI = startIndex + left.length;
    const index = endIndex + left.length;
    const [removed] = result.splice(startI, 1);
    const lastItem = result[index - 1] || {};
    if (lastItem.title !== '操作' && !lastItem.disabled) {
      result.splice(index, 0, removed);
      return result;
    } else {
      return list;
    }
  };

  reorderLeft = (list, startIndex, endIndex) => {
    const result = Array.from(list);
    const [removed] = result.splice(startIndex, 1);
    const lastItem = result[endIndex - 1] || {};
    if (lastItem.title !== '操作' && !lastItem.disabled) {
      result.splice(endIndex, 0, removed);
      return result;
    } else {
      return list;
    }
  };

  getListStyle = () => ({
    background: '#fff',
    width: 'auto',
  });

  getItemStyle = (isDragging, draggableStyle) => ({
    userSelect: 'none',
    padding: '8px 16px',
    background: isDragging ? '#fafafa' : '#fff',
    // borderBottom: '1px solid #f0f0f0',
    translation: 'background 0.1s',
    ...draggableStyle,
  });

  // 点选
  columnsOnCheck = (e) => {
    const state = this.state;
    const columnsLocal = state.columnsLocal;
    const name = e.target.value;
    const value = e.target.checked;
    // 过滤操作按钮
    if (!name || name === '操作') {
      return;
    }
    columnsLocal.forEach((item, i) => {
      if ([item.dataIndex, item.title].includes(name)) {
        columnsLocal[i].show = value;
      }
    });

    this.setState(
      {
        columnsLocal,
      },
      this.updateLocalColumns,
    );
  };

  filterOnCheck = (e) => {
    const state = this.state;
    const filterLocal = state.filterLocal;
    const name = e.target.value;
    const value = e.target.checked;
    // 过滤操作按钮
    if (!name) {
      return;
    }
    filterLocal.forEach((item, i) => {
      if ([item.value, item.label].includes(name)) {
        filterLocal[i].show = value;
      }
    });

    this.setState({ filterLocal }, this.updateLocalFilter);
  };

  // 全选
  columnsOnCheckAll = () => {
    const state = this.state;
    const checkout = state.checkout;

    if (checkout === 'table') {
      const columnsLocal = state.columnsLocal;
      const tableCheckedAll = !state.tableCheckedAll;
      columnsLocal.forEach((item, i) => {
        if (item.title !== '操作') {
          columnsLocal[i].show = tableCheckedAll;
        }
      });
      this.setState(
        {
          columnsLocal,
          tableCheckedAll,
        },
        this.updateLocalColumns,
      );
    }

    if (checkout === 'filter') {
      const filterLocal = state.filterLocal;
      const filterCheckedAll = !state.filterCheckedAll;
      filterLocal.forEach((item, i) => {
        if (item.title !== '操作') {
          filterLocal[i].show = filterCheckedAll;
        }
      });
      this.setState(
        {
          filterLocal,
          filterCheckedAll,
        },
        this.updateLocalFilter,
      );
    }
  };

  // 判断全选
  isSelectAll = (name) => {
    const { columnsLocal, filterLocal } = this.state;
    let tableSelectedLength = 0;
    let filterSelectedLength = 0;

    if (name === 'filter') {
      filterLocal.forEach((item) => {
        if (item.show) {
          filterSelectedLength += 1;
        }
      });

      if (filterSelectedLength === filterLocal.length) {
        return false;
      }
      return true;
    }

    if (name === 'table') {
      columnsLocal.forEach((item) => {
        if (item.show) {
          tableSelectedLength += 1;
        }
      });

      if (tableSelectedLength === columnsLocal.length) {
        return false;
      }
      return true;
    }
  };

  // 重置按钮 重置列表设置
  resetFilterColumns = () => {
    const state = this.state;
    const path = window.location.pathname;
    const tableId =
      state.tableId ||
      `table${localStorage.getItem('userId')}${path.replace(/\//g, '-')}`;
    const columnsId =
      state.columnsId ||
      `set1${localStorage.getItem('userId')}${path.replace(/\//g, '-')}`;
    const filterId =
      state.filterId ||
      `setFilter${localStorage.getItem('userId')}${path.replace(/\//g, '-')}`;

    if (state.checkout === 'filter') {
      //  触发事件
      localStorage.removeItem(filterId);
      EventsBus.emit(`${path}=refresh`, null);
      this.defaultLocalFilter();
      return;
    }
    try {
      localStorage.removeItem(tableId);
      localStorage.removeItem(columnsId);
      this.defaultPageSize();
      this.defaultLocalColumns();
    } catch (e) {
      console.log('可能不支持 localStorage', e);
    }
  };

  popconfirmRender = (name) => {
    const state = this.state;
    const { columnsFilter = [] } = this.props;
    if (name === 'title') {
      const rowStyle = {
        height: 32,
        lineHeight: '32px',
        fontSize: 14,
        paddingLeft: 16,
        paddingRight: 16,
        color: 'rgba(0,0,0,0.6)',
      };
      const setStyle = {
        fontSize: 16,
        paddingTop: 8,
        paddingBottom: 8,
        marginBottom: 8,
        marginTop: -8,
        color: 'rgba(0,0,0,0.6)',
        backgroundColor: '#fafafa',
      };

      const titleObj = {
        table: '表格展示',
        filter: '查询展示',
      };

      const checkoutFilter = () => {
        this.setState({ checkout: 'filter' });
      };
      const checkoutTable = () => {
        this.setState({ checkout: 'table' });
      };
      return (
        <div>
          {columnsFilter.length === 0 ? (
            <Row gutter={32} style={setStyle}>
              <Col
                span={24}
                align="left"
                className="title"
                style={{ paddingLeft: 30 }}
                // onClick={checkoutTable}
              >
                表格设置
              </Col>
            </Row>
          ) : (
            <Row gutter={32} style={setStyle}>
              <Col
                span={12}
                align="center"
                className="title"
                action={state.checkout === 'filter' ? 'active' : 0}
                style={{ cursor: 'pointer' }}
                onClick={checkoutFilter}
              >
                查询设置
              </Col>
              <Col
                span={12}
                align="center"
                className="title"
                action={state.checkout === 'table' ? 'active' : 0}
                style={{ cursor: 'pointer' }}
                onClick={checkoutTable}
              >
                表格设置
              </Col>
            </Row>
          )}

          <Row style={rowStyle}>
            <Col span={4}>
              <Checkbox
                indeterminate={this.isSelectAll(state.checkout)}
                checked={state.checkedAll}
                onChange={this.columnsOnCheckAll}
              />
            </Col>
            <Col span={16} align="left">
              {titleObj[state.checkout]}
            </Col>
            <Col span={4}>
              <Popconfirm
                title="确定重置吗?"
                onConfirm={this.resetFilterColumns}
              >
                <a>重置</a>
              </Popconfirm>
            </Col>
          </Row>
        </div>
      );
    }
    if (name === 'main') {
      return this.checkoutRender(state.checkout);
    }
  };

  checkoutRender = (name) => {
    const state = this.state;
    if (name === 'table') {
      const fixedLeftArray = state.columnsLocal.filter(
        (item) => item.fixed === 'left',
      );
      const fixedRightArray = state.columnsLocal.filter(
        (item) => item.fixed === 'right',
      );
      const fixedNullArray = state.columnsLocal.filter((item) => !item.fixed);
      const fixedNullHeight =
        fixedNullArray.length < 9 ? fixedNullArray.length * 40 : 360;
      const fixedLeftHeight =
        fixedLeftArray.length < 9 ? fixedLeftArray.length * 40 : 360;
      const fixedRightHeight =
        fixedRightArray.length < 9 ? fixedRightArray.length * 40 : 360;
      return (
        <div style={{ width: 250 }}>
          <div style={{ fontSize: 12, paddingLeft: 16, color: '#8c8c8c' }}>
            {!!fixedLeftArray.length && '固定左侧'}
          </div>

          <DragDropContext onDragEnd={this.onTableDragLeftEnd}>
            <div style={{ height: fixedLeftHeight, overflow: 'auto' }}>
              <Droppable droppableId="fixedLeftdroppable">
                {(provided, snapshot) => (
                  <div
                    {...provided.droppableProps}
                    ref={provided.innerRef}
                    style={this.getListStyle(snapshot)}
                  >
                    {fixedLeftArray.map((item, index) => (
                      <Draggable
                        index={index}
                        key={item.title}
                        draggableId={item.title}
                        isDragDisabled={item.title === '操作' || item.disabled}
                      >
                        {(provided2, snapshot2) => (
                          <div
                            {...provided2.draggableProps}
                            {...provided2.dragHandleProps}
                            ref={provided2.innerRef}
                            style={this.getItemStyle(
                              snapshot2.isDragging,
                              provided2.draggableProps.style,
                            )}
                          >
                            <Row>
                              <Col span={4} align="left">
                                <Checkbox
                                  checked={item.show}
                                  onChange={this.columnsOnCheck}
                                  value={item.dataIndex || item.title}
                                  disabled={
                                    item.title === '操作' || item.disabled
                                  }
                                />
                              </Col>
                              <Col span={16} align="left">
                                {item.title}
                              </Col>
                              <Col span={4}>
                                <Tooltip title="取消固定">
                                  {/* <Icon
                                    type="vertical-align-middle"
                                    style={{ marginRight: 4 }}
                                    onClick={this.tableFixedChange.bind(this, item, 0)}
                                  /> */}
                                </Tooltip>
                                <Tooltip title="固定右侧">
                                  {/* <Icon
                                    type="pushpin"
                                    onClick={this.tableFixedChange.bind(this, item, 1)}
                                  /> */}
                                </Tooltip>
                              </Col>
                            </Row>
                          </div>
                        )}
                      </Draggable>
                    ))}
                    {provided.placeholder}
                  </div>
                )}
              </Droppable>
            </div>
          </DragDropContext>

          <div style={{ fontSize: 12, paddingLeft: 16, color: '#8c8c8c' }}>
            {(!!fixedLeftArray.length || !!fixedRightArray.length) && '不固定'}
          </div>

          <DragDropContext onDragEnd={this.onTableDragEnd}>
            <div style={{ height: fixedNullHeight, overflow: 'auto' }}>
              <Droppable droppableId="droppable">
                {(provided, snapshot) => (
                  <div
                    {...provided.droppableProps}
                    ref={provided.innerRef}
                    style={this.getListStyle(snapshot)}
                  >
                    {fixedNullArray.map((item, index) => (
                      <Draggable
                        index={index}
                        key={item.title}
                        draggableId={item.title}
                        isDragDisabled={item.title === '操作' || item.disabled}
                      >
                        {(provided2, snapshot2) => (
                          <div
                            {...provided2.draggableProps}
                            {...provided2.dragHandleProps}
                            ref={provided2.innerRef}
                            style={this.getItemStyle(
                              snapshot2.isDragging,
                              provided2.draggableProps.style,
                            )}
                          >
                            <Row>
                              <Col span={4} align="left">
                                <Checkbox
                                  checked={item.show}
                                  onChange={this.columnsOnCheck}
                                  value={item.dataIndex || item.title}
                                  disabled={
                                    item.title === '操作' || item.disabled
                                  }
                                />
                              </Col>
                              <Col span={16} align="left">
                                {item.title}
                              </Col>
                              <Col span={4}>
                                <Tooltip title="固定左侧">
                                  {/* <PushpinOutlined
                                    rotate={-90}
                                    style={{ marginRight: 4 }}
                                    onClick={this.tableFixedChange.bind(this, item, -1)}
                                  /> */}
                                </Tooltip>
                                <Tooltip title="固定右侧">
                                  {/* <PushpinOutlined
                                    rotate={-90}
                                    style={{ marginRight: 4 }}
                                    onClick={this.tableFixedChange.bind(this, item, 1)}
                                  /> */}
                                </Tooltip>
                              </Col>
                            </Row>
                          </div>
                        )}
                      </Draggable>
                    ))}
                    {provided.placeholder}
                  </div>
                )}
              </Droppable>
            </div>
          </DragDropContext>

          <div style={{ fontSize: 12, paddingLeft: 16, color: '#8c8c8c' }}>
            {!!fixedRightArray.length && '固定右侧'}
          </div>

          <DragDropContext onDragEnd={this.onTableDragRightEnd}>
            <div style={{ height: fixedRightHeight, overflow: 'auto' }}>
              <Droppable droppableId="fixedRightdroppable">
                {(provided, snapshot) => (
                  <div
                    {...provided.droppableProps}
                    ref={provided.innerRef}
                    style={this.getListStyle(snapshot)}
                  >
                    {fixedRightArray.map((item, index) => (
                      <Draggable
                        index={index}
                        key={item.title}
                        draggableId={item.title}
                        isDragDisabled={item.title === '操作' || item.disabled}
                      >
                        {(provided2, snapshot2) => (
                          <div
                            {...provided2.draggableProps}
                            {...provided2.dragHandleProps}
                            ref={provided2.innerRef}
                            style={this.getItemStyle(
                              snapshot2.isDragging,
                              provided2.draggableProps.style,
                            )}
                          >
                            <Row>
                              <Col span={4} align="left">
                                <Checkbox
                                  checked={item.show}
                                  onChange={this.columnsOnCheck}
                                  value={item.dataIndex || item.title}
                                  disabled={
                                    item.title === '操作' || item.disabled
                                  }
                                />
                              </Col>
                              <Col span={16} align="left">
                                {item.title}
                              </Col>
                              <Col span={4}>
                                <Tooltip title="固定左侧">
                                  {/* <Icon
                                    type="pushpin"
                                    rotate={-90}
                                    style={{ marginRight: 4 }}
                                    onClick={this.tableFixedChange.bind(this, item, -1)}
                                  /> */}
                                </Tooltip>

                                <Tooltip title="取消固定">
                                  {/* <Icon
                                    type="vertical-align-middle"
                                    onClick={this.tableFixedChange.bind(this, item, 0)}
                                  /> */}
                                </Tooltip>
                              </Col>
                            </Row>
                          </div>
                        )}
                      </Draggable>
                    ))}
                    {provided.placeholder}
                  </div>
                )}
              </Droppable>
            </div>
          </DragDropContext>
        </div>
      );
    }

    if (name === 'filter') {
      const filterHeight =
        state.filterLocal.length < 9 ? state.filterLocal.length * 40 : 360;
      return (
        <div style={{ width: 250 }}>
          <DragDropContext onDragEnd={this.onFilterDragEnd}>
            <div style={{ height: filterHeight, overflow: 'auto' }}>
              <Droppable droppableId="droppable2">
                {(provided, snapshot) => (
                  <div
                    {...provided.droppableProps}
                    ref={provided.innerRef}
                    style={this.getListStyle(snapshot)}
                  >
                    {state.filterLocal.map((item, index) => (
                      <Draggable
                        index={index}
                        key={item.label}
                        draggableId={item.label}
                      >
                        {(provided2, snapshot2) => (
                          <div
                            {...provided2.draggableProps}
                            {...provided2.dragHandleProps}
                            ref={provided2.innerRef}
                            style={this.getItemStyle(
                              snapshot2.isDragging,
                              provided2.draggableProps.style,
                            )}
                          >
                            <Row>
                              <Col span={4} align="left">
                                <Checkbox
                                  checked={item.show}
                                  onChange={this.filterOnCheck}
                                  value={item.label}
                                />
                              </Col>
                              <Col span={20} align="left">
                                {item.label}
                              </Col>
                            </Row>
                          </div>
                        )}
                      </Draggable>
                    ))}
                    {provided.placeholder}
                  </div>
                )}
              </Droppable>
            </div>
          </DragDropContext>
        </div>
      );
    }
  };

  render() {
    const state = this.state;
    const props = this.props;
    const { settings } = props;
    // this.i += 1;
    // console.log(props.page, '表格设置渲染次数：', this.i);
    let width = 0;
    const columns = state.columns.map((col, index) => {
      width += col.width || 0;
      return {
        ...col,
        sortOrder: state.sorter.columnKey === col.key && state.sorter.order, // 排序受控
        onHeaderCell: (column) => ({
          width: column.width,
          onResize: this.handleResize(index),
        }),
      };
    });

    width = width > document.body.clientWidth - 100 ? width : undefined;

    return (
      <div
        className="table-container-fixed"
        style={{ position: 'relative', overflow: 'hidden' }}
      >
        {!!state.fixed && (
          <div style={state.fixedStyle} className="fixed-table">
            <Table
              columns={columns}
              scroll={{ x: width }}
              size={state.columnHeight}
              onChange={this.onPageChange}
              // components={this.components}
              dataSource={[]}
              // bordered={this.props.bordered}
              className={['tableFixed', `tableFixed${state.tableId}`]}
            />
          </div>
        )}
        <React.Fragment>
          {props.tableHeader
            ? props.tableHeader(
                <>
                  <Tooltip title="密度">
                    <Dropdown
                      trigger="click"
                      overlay={
                        <Menu
                          selectable
                          onClick={this.columnHeightChange}
                          selectedKeys={[state.columnHeight]}
                        >
                          <Menu.Item key="default">默认</Menu.Item>
                          <Menu.Item key="middle">中等</Menu.Item>
                          <Menu.Item key="small">紧凑</Menu.Item>
                        </Menu>
                      }
                    >
                      <ColumnHeightOutlined
                        style={{ fontSize: 16, marginLeft: 16 }}
                      />
                    </Dropdown>
                  </Tooltip>

                  <Tooltip title={state.isFullScreen ? '退出全屏' : '全屏'}>
                    {/* <Icon
                    onClick={this.tableFullScreen}
                    style={{ fontSize: 16, marginLeft: 16 }}
                    type={state.isFullScreen ? 'fullscreen-exit' : 'fullscreen'}
                  /> */}
                    {state.isFullScreen ? (
                      <FullscreenExitOutlined
                        onClick={this.tableFullScreen}
                        style={{ fontSize: 16, marginLeft: 16 }}
                      />
                    ) : (
                      <FullscreenOutlined
                        onClick={this.tableFullScreen}
                        style={{ fontSize: 16, marginLeft: 16 }}
                      />
                    )}
                  </Tooltip>

                  <Tooltip title="刷新">
                    <ReloadOutlined
                      style={{ fontSize: 16, marginLeft: 16 }}
                      onClick={this.pageReLoad}
                    />
                  </Tooltip>

                  <Tooltip title="设置">
                    <Popover
                      trigger="click"
                      // destroyTooltipOnHide
                      // getPopupContainer={()=>document.querySelector('.ant-tabs.ant-tabs-card')}
                      autoAdjustOverflow={false}
                      placement="bottomRight"
                      arrowPointAtCenter
                      zIndex={4}
                      className="table-setting"
                      title={this.popconfirmRender('title')}
                      content={this.popconfirmRender('main')}
                    >
                      <SettingOutlined
                        style={{ fontSize: 16, marginLeft: 16 }}
                      />
                    </Popover>
                  </Tooltip>
                </>,
              )
            : null}

          <Table
            {...this.props}
            columns={columns}
            // bordered={[3, 4].includes(tableSelected)}
            scroll={{ x: width }}
            size={state.columnHeight}
            components={this.components}
            onChange={this.onPageChange}
            pagination={props.noPagination ? false : props.pagination}
            // style={{ minWidth: '100%' }}
            dataSource={props.dataSource || []}
            className={[
              'tableNormal',
              `tableNormal${state.tableId}`,
              `tableModal-${settings.tableLayout}`,
              state.fixed && 'noScroll',
            ]}
            bordered={['verticalLine', 'zebraVerticalLine'].includes(
              settings.tableLayout,
            )}
          />
        </React.Fragment>
      </div>
    );
  }
}
FlexibleTable.defaultProps = {
  settings: {},
};
// 监听这些数据的变化 ['mutilModel','collapsed'] todo 这些数据如果有变化，组件就会获取新的 setting
export default connect(['mutilModel', 'collapsed', 'tableLayout'])(
  React.memo(FlexibleTable),
);
